%{
	#include <process.h>
	#include <string.h>
	#include <malloc.h>
	#include "grammar.tab.h"

	extern int yyparse(void);
	extern int yyerror(char * s);
	
	int myint;
	char str[100] = {0};		//хранит строковые константы
	char comment[1024];	//хранит комментарии
	char c;				//хранит символ
	int error = 0;		//хранит состояние, не дошли ли до ошибки

%}
%option noyywrap
%option never-interactive
%option yylineno

%x STRING
%x ONE_COMMENT
%x MANY_COMMENTS
%x CHARACTER

%%

[1-9][0-9]* {
	sscanf(yytext, "%d", &myint);
	yylval.int_const = myint;
	return CONSTANT;
}
0[0-7]* {
	sscanf(yytext, "%o", &myint);
	yylval.int_const = myint;
	return CONSTANT;
}
0x[A-Fa-f0-9]+ {
	sscanf(yytext, "%x", &myint);
	yylval.int_const = myint;
	return CONSTANT;
}

"\'" {
	BEGIN(CHARACTER); c = 0;
}

<CHARACTER>\\a\' 	{ yylval.int_const = '\a'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\b\' 	{ yylval.int_const = '\b'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\f\' 	{ yylval.int_const = '\f'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\n\' 	{ yylval.int_const = '\n'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\r\' 	{ yylval.int_const = '\r'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\t\' 	{ yylval.int_const = '\t'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\v\' 	{ yylval.int_const = '\v'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\\\\' 	{ yylval.int_const = '\\'; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\\"\' 	{ yylval.int_const = '"';  BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\\'\' 	{ yylval.int_const = '\''; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\\\?\' 	{ yylval.int_const = '?';  BEGIN(INITIAL); return CHAR;}
<CHARACTER>[^\\]\' 	{ yylval.int_const = yytext[0]; BEGIN(INITIAL); return CHAR;}
<CHARACTER>\' 		{ yylval.int_const = 0; BEGIN(INITIAL); return CHAR;}
<CHARACTER>.		{ yylval.int_const = 0; error = 1; printf("Символ из более чем одного элемента\n"); BEGIN(INITIAL); }
"@\"" { 
	BEGIN(STRING);
	str[0] = 0;
}
<STRING>[^\"\\\n]+ strcat(str, yytext);
<STRING>\\a strcat(str, "\a");
<STRING>\\b strcat(str, "\b");
<STRING>\\f strcat(str, "\f");
<STRING>\\n strcat(str, "\n");
<STRING>\\r strcat(str, "\r");
<STRING>\\t strcat(str, "\t");
<STRING>\\v strcat(str, "\v");
<STRING>\\\\ strcat(str, "\\");
<STRING>\\\" strcat(str, "\"");
<STRING>\\\' strcat(str, "'");
<STRING>\\\? strcat(str, "?");
<STRING>\" { 
	yylval.string_const = (char *)malloc(strlen(str) + 1);  
	strcpy(yylval.string_const, str); 
	BEGIN(INITIAL);
	return STRING_LITERAL; 
}

"/*" BEGIN(MANY_COMMENTS); 
<MANY_COMMENTS>[^*]+ //strcat(comment, yytext);
<MANY_COMMENTS>"*"+"/" { 
	/*strcat(comment, yytext);
	comment[strlen(comment) - 3] = 0;
	printf("Многострочный комментарий %s\n",comment);*/
	comment[0] = 0;
	BEGIN(INITIAL);
}
<MANY_COMMENTS>"*"+[^/]\n* strcat(comment, yytext);

"//" BEGIN(ONE_COMMENT);
<ONE_COMMENT>.* {
	//strcat(comment, yytext); 
	//printf("Однострочный комментарий %s\n",comment);
	comment[0]=0;
	BEGIN(INITIAL);
}

"int" 				return INT;
"void" 				return VOID;
"char" 				return CHAR;
"NSString" 			return NSSTRING;
"@interface" 		return INTERFACE;
"@implementation" 	return IMPLEMENTATION;
"@end" 				return END;
"self" 				return SELF;
"super" 			return SUPER;
"enum" 				return ENUM;
"return" 			return RETURN;
"do" 				return DO;
"while" 			return WHILE;
"for" 				return FOR;
"if" 				return IF;
"else" 				return ELSE;
"switch" 			return SWITCH;
"case" 				return CASE;
"break" 			return BREAK;
"default" 			return DEFAULT;
"new" 				return NEW;

"(" return '(';
")" return ')';

"=" return '=';

"||"  return OR_OP;
"&&"  return AND_OP;

"<" return '<';
"<=" return LE_OP;
"==" return EQ_OP;

"+" return '+';
"-" return '-';
"*" return '*';
"/" return '/';
"%" return '%';

"{" return '{';
"}" return '}';

"!"  return '!';

"[" return '[';
"]" return ']';

":" return ':';
"," return ',';
"." return '.';

";" return ';';

[A-Za-z_][A-Za-z_0-9]* { 
	yylval.id = (char *)malloc(strlen(yytext)+1);  
	strcpy(yylval.id, yytext); 
	return IDENTIFIER; 
}

[[:blank:]]+
[\n\t]+
. { printf("Eror, unexpected symbol %s\n", yytext); error = 1; }


%%

int yyerror(char * s)
{
	printf("Error!\n%s on line %d\n", s, yylineno);
	return -1;
}